package com.lky.marshall.mallcart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lky.common.constant.CartConstant;
import com.lky.common.utils.Constant;
import com.lky.common.utils.R;
import com.lky.marshall.mallcart.feign.ProductFeignService;
import com.lky.marshall.mallcart.interceptor.CartInterceptor;
import com.lky.marshall.mallcart.service.CartService;
import com.lky.marshall.mallcart.vo.CartItemVo;
import com.lky.marshall.mallcart.vo.CartVo;
import com.lky.marshall.mallcart.vo.SkuInfoVo;
import com.lky.marshall.mallcart.vo.UserInfoTo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * Created by
 * autor : Marshall lky
 * datetime: 2021/6/1 10:19
 */
@Slf4j
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProductFeignService productFeignService;
    @Autowired
    private ThreadPoolExecutor executor;

    @Override
    public CartItemVo addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String cacheJson = (String) cartOps.get(skuId.toString());
        if (!StringUtils.isBlank(cacheJson)) {
            //购物车中有该商品
            CartItemVo cartItemVo = JSON.parseObject(cacheJson, CartItemVo.class);
            cartItemVo.setCount(cartItemVo.getCount() + num);
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItemVo));
            return cartItemVo;
        }

        //2.新商品添加到购物车
        CartItemVo cartItemVo = new CartItemVo();
        CompletableFuture<Void> getSkuInfo = CompletableFuture.runAsync(() -> {
            //1.远程查询商品信息
            R<SkuInfoVo> info = productFeignService.info(skuId);
            SkuInfoVo data = info.getData(new TypeReference<SkuInfoVo>() {
            });
            cartItemVo.setSkuId(skuId);
            cartItemVo.setCheck(true);
            cartItemVo.setCount(num);
            cartItemVo.setImage(data.getSkuDefaultImg());
            cartItemVo.setTitle(data.getSkuTitle());
            cartItemVo.setPrice(data.getPrice());
        }, executor);

        //3远程查询sku的组合信息
        CompletableFuture<Void> getSkuSaleAttrValues = CompletableFuture.runAsync(() -> {
            List<String> skuSaleAttrValues = productFeignService.getSkuSaleAttrValues(skuId);
            cartItemVo.setSkuAttr(skuSaleAttrValues);
        }, executor);
        CompletableFuture.allOf(getSkuInfo, getSkuSaleAttrValues).get();

        //转成json，不使用默认的jdk序列化
        String s = JSON.toJSONString(cartItemVo);
        cartOps.put(skuId.toString(), s);

        return cartItemVo;
    }

    /**
     * 获取购物车中的某个购物项
     *
     * @param skuId
     * @return
     */
    @Override
    public CartItemVo getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String cacheJson = (String) cartOps.get(skuId.toString());
        CartItemVo cartItemVo = JSON.parseObject(cacheJson, CartItemVo.class);
        return cartItemVo;
    }

    @Override
    public CartVo getCart() throws ExecutionException, InterruptedException {
        CartVo cartVo = new CartVo();
        //使用threadLocal判断用户是否登录
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        if (userInfoTo.getUserId() != null) {
            //登录
            String cartKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserId();
            //如果临时购物车有数据，——》合并
            String tempKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserKey();
            List<CartItemVo> tempCartItems = getCartItems(tempKey);
            if (tempCartItems != null && tempCartItems.size() > 0) {
                //临时购物车有数据 添加商品
                for (CartItemVo tempCartItem : tempCartItems) {
                    addToCart(tempCartItem.getSkuId(), tempCartItem.getCount());
                }
                //清空临时购物车
                clearCartKey(tempKey);
            }
            //获取登陆后的购物车[包含合并的临时购物车]
            List<CartItemVo> cartItems = getCartItems(cartKey);
            cartVo.setCartItems(cartItems);
        } else {
            String cartKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserKey();
            //获取临时购物车的所有购物项
            List<CartItemVo> cartItems = getCartItems(cartKey);
            cartVo.setCartItems(cartItems);
        }
        return cartVo;
    }

    /**
     * 获取操作的购物车
     *
     * @return
     */
    private BoundHashOperations<String, Object, Object> getCartOps() {
        //使用threadLocal判断用户是否登录
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        String cartKey = "";
        if (userInfoTo.getUserId() != null) {
            //登录
            cartKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserId();
        } else {
            cartKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserKey();
        }
        BoundHashOperations<String, Object, Object> cartRedisBound = redisTemplate.boundHashOps(cartKey);
        return cartRedisBound;
    }


    private List<CartItemVo> getCartItems(String cartKey) {
        CartVo cartVo = new CartVo();
        BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(cartKey);
        List<Object> values = hashOps.values();
        if (values != null && values.size() > 0) {
            List<CartItemVo> collect = values.stream().map(obj -> {
                String str = (String) obj;
                CartItemVo cartItemVo = JSON.parseObject(str, CartItemVo.class);
                return cartItemVo;
            }).collect(Collectors.toList());
            return collect;
        }
        return null;
    }

    @Override
    public void clearCartKey(String cartKey){
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartItemVo> getCurrentUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        if (userInfoTo == null){
            return null;
        }
        String cartKey = CartConstant.CART_REDIS_PREFIX + userInfoTo.getUserId();
        List<CartItemVo> cartItems = getCartItems(cartKey);

        //过滤被选中的购物项
        return cartItems.stream().filter(cartItemVo -> cartItemVo.getCheck()).map(item->{
            R price = productFeignService.getPrice(item.getSkuId());
            Double data = (Double) price.get("data");
            item.setPrice(new BigDecimal(data));
            return item;
        }).collect(Collectors.toList());
    }
}
